home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / c / hce.lha / HCE / LibSource / clib / Stdio / src / printf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-02  |  5.1 KB  |  276 lines

  1. #include <stdio.h>
  2. #include <ctype.h>
  3. #include <string.h>
  4.  
  5. /* From the Hcc.lib by Detlef Wurkner, Placed here by J.P. */
  6. /* Modified by J.P. */
  7. /* This version of printf does not suport floats, if you need float printf */
  8. /* link the math.lib as first library in list. */
  9.  
  10. #define    FALSE    (0)
  11. #define TRUE    (!FALSE)
  12.  
  13. static char    _numstr[] = "0123456789ABCDEF";
  14.  
  15. static char *_strlwr(string)
  16.     register char *string;
  17.     {
  18.     register char *p = string;
  19.  
  20.     while(*string)
  21.         tolower(*string++);
  22.     return(p);
  23.     }
  24.  
  25. static char *_ultoa(n, buffer, radix)
  26.     register unsigned long n;
  27.     register char *buffer;
  28.     register int radix;
  29.     {
  30.     register char *p = buffer;
  31.  
  32.     do
  33.         {
  34.         *p++ = _numstr[n % radix];    /* grab each digit */
  35.         }
  36.         while((n /= radix) > 0);
  37.     *p = '\0';
  38.     return(strrev(buffer));            /* reverse and return it */
  39.     }
  40.  
  41. static char *_ltoa(n, buffer, radix)
  42.     register long n;
  43.     register char *buffer;
  44.     int radix;
  45.     {
  46.     register char *p = buffer;
  47.  
  48.     if (n < 0)
  49.         {
  50.         *p++ = '-';
  51.         n = -n;
  52.         }
  53.     _ultoa(n, p, radix);
  54.     return(buffer);
  55.     }
  56.  
  57. static _prtfld(op, put, buf, ljustf, sign, pad, width, preci)
  58.     register char *op;
  59.     register int (*put)();
  60.     register unsigned char *buf;
  61.     int ljustf;
  62.     register char sign;
  63.     char pad;
  64.     register int width;
  65.     int preci;
  66. /*
  67.  *    Output the given field in the manner specified by the arguments.
  68.  *    Return the number of characters output.
  69.  */
  70.     {
  71.     register int cnt = 0, len;
  72.     register unsigned char ch;
  73.  
  74.     len = strlen(buf);
  75.  
  76.     if (*buf == '-')
  77.         sign = *buf++;
  78.     else if (sign)
  79.         len++;
  80.  
  81.     if ((preci != -1) && (len > preci))    /* limit max data width */
  82.         len = preci;
  83.  
  84.     if (width < len)    /* flexible field width or width overflow */
  85.         width = len;
  86.  
  87. /* at this point:
  88.  *    width = total field width
  89.  *    len   = actual data width (including possible sign character)
  90.  */
  91.     cnt = width;
  92.     width -= len;
  93.  
  94.     while (width || len)
  95.         {
  96.         if (!ljustf && width)        /* left padding */
  97.             {
  98.             if (len && sign && (pad == '0'))
  99.                 goto showsign;
  100.             ch = pad;
  101.             --width;
  102.             }
  103.         else if (len)
  104.             {
  105.             if (sign)
  106.                 {
  107. showsign:            ch = sign;    /* sign */
  108.                 sign = '\0';
  109.                 }
  110.             else
  111.                 ch = *buf++;    /* main field */
  112.             --len;
  113.             }
  114.         else
  115.             {
  116.             ch = pad;        /* right padding */
  117.             --width;
  118.             }
  119.         (*put)(ch, op);
  120.         }
  121.  
  122.     return(cnt);
  123.     }
  124.  
  125.  
  126. _printf(op, put, fmt, args)
  127.     char *op;
  128.     unsigned int (*put)();
  129.     register unsigned char *fmt;
  130.     register unsigned int *args;
  131.     {
  132.     register int i, cnt = 0, ljustf, lval;
  133.     int preci, dpoint, width;
  134.     char pad, sign, radix;
  135.     register char *ptmp;
  136.     char tmp[64], *_ltoa(), *_ultoa();
  137.  
  138.     while(*fmt)
  139.         {
  140.         if(*fmt == '%')
  141.             {
  142.             ljustf = FALSE;    /* left justify flag */
  143.             sign = '\0';    /* sign char & status */
  144.             pad = ' ';    /* justification padding char */
  145.             width = -1;    /* min field width */
  146.             dpoint = FALSE;    /* found decimal point */
  147.             preci = -1;    /* max data width */
  148.             radix = 10;    /* number base */
  149.             ptmp = tmp;    /* pointer to area to print */
  150.             lval = FALSE;    /* long value flaged */
  151. fmtnxt:
  152.             i = 0;
  153.             while (isdigit(*++fmt))
  154.                 {
  155.                 i = (i * 10) + (*fmt - '0');
  156.                 if (dpoint)
  157.                     preci = i;
  158.                 else if (!i && (pad == ' '))
  159.                     {
  160.                     pad = '0';
  161.                     goto fmtnxt;
  162.                     }
  163.                 else
  164.                     width = i;
  165.                 }
  166.  
  167.             switch(*fmt)
  168.                 {
  169.                 case '\0':    /* early EOS */
  170.                     --fmt;
  171.                     goto charout;
  172.  
  173.                 case '-':    /* left justification */
  174.                     ljustf = TRUE;
  175.                     goto fmtnxt;
  176.  
  177.                 case ' ':
  178.                 case '+':    /* leading sign flag */
  179.                     sign = *fmt;
  180.                     goto fmtnxt;
  181.  
  182.                 case '*':    /* parameter width value */
  183.                     i = *args++;
  184.                     if (dpoint)
  185.                         preci = i;
  186.                     else
  187.                         width = i;
  188.                     goto fmtnxt;
  189.  
  190.                 case '.':    /* secondary width field */
  191.                     dpoint = TRUE;
  192.                     goto fmtnxt;
  193.  
  194.                 case 'l':    /* long data */
  195.                     lval = TRUE;
  196.                     goto fmtnxt;
  197.  
  198.                 case 'd':    /* Signed decimal */
  199.                 case 'i':
  200.                     _ltoa((long)((lval)
  201.                         ?(*((long *) args))
  202.                         :(*((int  *) args))),
  203.                           ptmp, 10);
  204.                     if(lval)
  205.                         args = ((unsigned int *)
  206.                             (((long *) args) + 1));
  207.                     else
  208.                         args = ((unsigned int *)
  209.                             (((int *) args) + 1));
  210.                     goto printit;
  211.  
  212.                 case 'b':    /* Unsigned binary */
  213.                     radix = 2;
  214.                     goto usproc;
  215.  
  216.                 case 'o':    /* Unsigned octal */
  217.                     radix = 8;
  218.                     goto usproc;
  219.  
  220.                 case 'p':    /* Pointer */
  221.                     lval = TRUE;
  222.                     pad = '0';
  223.                     width = 6;
  224.                     preci = 8;
  225.                     /* fall thru */
  226.  
  227.                 case 'x':    /* Unsigned hexadecimal */
  228.                 case 'X':
  229.                     radix = 16;
  230.                     /* fall thru */
  231.  
  232.                 case 'u':    /* Unsigned decimal */
  233. usproc:
  234.                     _ultoa((unsigned long)((lval)
  235.                         ?(*((unsigned long *) args))
  236.                         : *args++ ),
  237.                           ptmp, radix);
  238.                     if(lval)
  239.                         args = ((unsigned int *)
  240.                         (((unsigned long *) args) + 1));
  241.                     if (*fmt == 'x')
  242.                         _strlwr(ptmp);
  243.                     goto printit;
  244.  
  245.                 case 'c':    /* Character */
  246.                     ptmp[0] = *args++;
  247.                     ptmp[1] = '\0';
  248.                     goto nopad;
  249.  
  250.                 case 's':    /* String */
  251.                     ptmp = *((char **) args);
  252.                     args = ((unsigned int *)
  253.                         (((char **) args) + 1));
  254. nopad:
  255.                     sign = '\0';
  256.                     pad  = ' ';
  257. printit:
  258.                     cnt += _prtfld(op, put, ptmp, ljustf,
  259.                                sign, pad, width, preci);
  260.                     break;
  261.  
  262.                 default:    /* unknown character */
  263.                     goto charout;
  264.                 }
  265.             }
  266.         else
  267.             {
  268. charout:
  269.             (*put)(*fmt, op);        /* normal char out */
  270.             ++cnt;
  271.             }
  272.         ++fmt;
  273.         }
  274.     return(cnt);
  275.     }
  276.